package com.jinunn.user.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.yygh.enums.AuthStatusEnum;
import com.atguigu.yygh.model.user.Patient;
import com.atguigu.yygh.model.user.UserInfo;
import com.atguigu.yygh.vo.user.LoginVo;
import com.atguigu.yygh.vo.user.UserAuthVo;
import com.atguigu.yygh.vo.user.UserInfoQueryVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jinunn.common.exception.YyghException;
import com.jinunn.common.helper.JwtHelper;
import com.jinunn.common.result.ResultCodeEnum;
import com.jinunn.common.utils.AuthContextHolder;
import com.jinunn.user.mapper.UserInfoMapper;
import com.jinunn.user.service.PatientService;
import com.jinunn.user.service.UserInfoService;
import com.jinunn.user.utils.ConstantWxPropertiesUtils;
import com.jinunn.user.utils.HttpClientUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author JinDun
 * @date 2021/5/11 22:55
 */
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private PatientService patientService;

    @Override
    public Map<String, Object> loginUser(LoginVo loginVo) {
        String phone = loginVo.getPhone();
        String code = loginVo.getCode();
        //1、判断手机号和验证码是否为空
        if (StringUtils.isBlank(phone) && StringUtils.isBlank(code)) {
            throw new YyghException(ResultCodeEnum.PARAM_ERROR);
        }

        //判断手机发送的验证码和接受到的验证码是否一致
        String smsCode = redisTemplate.opsForValue().get(phone);
        if (!code.equals(smsCode)) {
            throw new YyghException(ResultCodeEnum.PARAM_ERROR);
        }

        //微信登录需要绑定手机号
        UserInfo userInfo = null;
        if (StringUtils.isBlank(loginVo.getOpenid())) {
            userInfo = baseMapper.selectOne(new QueryWrapper<UserInfo>().eq("openid", loginVo.getOpenid()));
            if (null != userInfo) {
                userInfo.setPhone(loginVo.getPhone());
                this.updateById(userInfo);
            } else {
                throw new YyghException(ResultCodeEnum.DATA_ERROR);
            }
        }

        // 判断是否为第一次登录：根据手机号查询数据库，如果不存在相同的手机号就是第一次登录
        if (null == userInfo) {
            userInfo = baseMapper.selectOne(new QueryWrapper<UserInfo>().eq("phone", phone));
            if (userInfo == null) {
                userInfo = new UserInfo();
                userInfo.setName("");
                userInfo.setPhone(phone);
                userInfo.setStatus(1);
                baseMapper.insert(userInfo);
            }
        }

        //校验账号是否被禁用
        if (userInfo.getStatus() == 0) {
            throw new YyghException(ResultCodeEnum.LOGIN_DISABLED_ERROR);
        }

        //返回登录用户名
        String name = userInfo.getName();
        if (StringUtils.isBlank(name)) {
            //如果name为空，就返会昵称
            name = userInfo.getNickName();
        }
        if (StringUtils.isBlank(name)) {
            //如果昵称为空，就返回手机号
            name = userInfo.getPhone();
        }
        //生成token
        String token = JwtHelper.createToken(userInfo.getId(), name);

        Map<String, Object> map = new HashMap<>();
        map.put("name", name);
        map.put("token", token);
        return map;
    }

    @Override
    public Map<String, Object> callback(String code, String state) {
        StringBuffer baseAccessTokenUrl = new StringBuffer()
                .append("https://api.weixin.qq.com/sns/oauth2/access_token")
                .append("?appid=%s")
                .append("&secret=%s")
                .append("&code=%s")
                .append("&grant_type=authorization_code");
        // 1、使用code和appid以及appscrect换取access_token
        // String.format 可以设置%s的值
        String accessTokenUrl = String.format(baseAccessTokenUrl.toString(),
                ConstantWxPropertiesUtils.WX_OPEN_APP_ID,
                ConstantWxPropertiesUtils.WX_OPEN_APP_SECRET,
                code);

        // 2、使用httpclient请求这个地址
        try {
            String accessTokenInfo = HttpClientUtils.get(accessTokenUrl);
            //从返回字符串获取两个值 openid  和  access_token
            JSONObject jsonObject = JSONObject.parseObject(accessTokenInfo);
            String accessToken = jsonObject.getString("access_token");
            String openid = jsonObject.getString("openid");

            //判断数据库是否存在
            UserInfo userInfo = baseMapper.selectOne(new QueryWrapper<UserInfo>().eq("openid", openid));
            if (userInfo == null) {
                //3、 拿着openid 和 access_token请求微信地址，得到扫描人信息
                String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                        "?access_token=%s" +
                        "&openid=%s";
                String userInfoUrl = String.format(baseUserInfoUrl, accessToken, openid);

                String resultInfo = HttpClientUtils.get(userInfoUrl);
                System.out.println("resultInfo:" + resultInfo);
                JSONObject resultUserInfoJson = JSONObject.parseObject(resultInfo);
                //解析用户信息
                //用户昵称
                String nickName = resultUserInfoJson.getString("nickname");
                //用户头像
                String headImgUrl = resultUserInfoJson.getString("headimgurl");

                //4、保存到数据库
                userInfo = new UserInfo();
                userInfo.setNickName(nickName);
                userInfo.setOpenid(openid);
                userInfo.setStatus(1);
                baseMapper.insert(userInfo);
            }
            //5、返回name和token字符串给前端
            Map<String, Object> map = new HashMap<>();
            String name = userInfo.getName();
            if (StringUtils.isBlank(name)) {
                name = userInfo.getNickName();
            }
            if (StringUtils.isBlank(name)) {
                name = userInfo.getPhone();
            }
            map.put("name", name);

            // 判断userInfo是否有手机号，如果手机号为空，返回openid, 如果手机号不为空，返回openid值是空字符串
            // 然后前端判断：如果openid不为空，绑定手机号，如果openid为空，不需要绑定手机号
            if (StringUtils.isEmpty(userInfo.getPhone())) {
                map.put("openid", userInfo.getOpenid());
            } else {
                map.put("openid", "");
            }
            String token = JwtHelper.createToken(userInfo.getId(), name);
            map.put("token", token);
            //跳转到前端页面
            //return "redirect:" + ConstantWxPropertiesUtils.YYGH_BASE_URL + "/weixin/callback?token=" +map.get("token")
            //        + "&openid=" +map.get("openid")
            //        + "&name=" +URLEncoder.encode(map.get("name"),"utf-8");
            return map;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void userAuth(UserAuthVo userAuthVo, Long userId) {
        UserInfo userInfo = baseMapper.selectById(userId);
        //设置认证信息
        userInfo.setName(userAuthVo.getName());
        userInfo.setCertificatesType(userAuthVo.getCertificatesType());
        userInfo.setCertificatesNo(userAuthVo.getCertificatesNo());
        userInfo.setCertificatesUrl(userAuthVo.getCertificatesUrl());
        userInfo.setAuthStatus(AuthStatusEnum.AUTH_RUN.getStatus());
        //更新
        baseMapper.updateById(userInfo);
    }

    @Override
    public UserInfo getUserDetail(HttpServletRequest request) {
        Long userId = AuthContextHolder.getUserId(request);
        return baseMapper.selectById(userId);
    }

    @Override
    public Page<UserInfo> getList(Long page, Long limit, UserInfoQueryVo infoQueryVo) {
        Page<UserInfo> page1 = new Page<>(page, limit);
        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();

        //名称
        if (StringUtils.isNotBlank(infoQueryVo.getKeyword())) {
            wrapper.like("name", infoQueryVo.getKeyword());
        }

        if (StringUtils.isNotBlank(infoQueryVo.getStatus().toString())) {
            wrapper.eq("status", infoQueryVo.getStatus());
        }

        if (StringUtils.isNotBlank(infoQueryVo.getAuthStatus().toString())) {
            wrapper.eq("auth_status", infoQueryVo.getAuthStatus());
        }

        if (StringUtils.isNotBlank(infoQueryVo.getCreateTimeEnd())) {
            //大于等于
            wrapper.ge("create_time", infoQueryVo.getCreateTimeEnd());
        }

        if (StringUtils.isNotBlank(infoQueryVo.getCreateTimeBegin())) {
            //小于
            wrapper.le("create_time", infoQueryVo.getCreateTimeEnd());
        }

        Page<UserInfo> userInfoPage = baseMapper.selectPage(page1, wrapper);
        userInfoPage.getRecords().forEach(userInfo -> {
            userInfo.getParam().put("authStater", AuthStatusEnum.getStatusNameByStatus(userInfo.getAuthStatus()));
            userInfo.getParam().put("status", userInfo.getStatus() == 0 ? "锁定" : "正常");
        });
        return userInfoPage;
    }

    @Override
    public boolean updateStatus(Integer userId, Integer status) {
        if (status == 0 || status == 1) {
            UserInfo userInfo = baseMapper.selectById(userId);
            userInfo.setStatus(status);
            int result = baseMapper.updateById(userInfo);
            return result > 0;
        }
        return false;
    }

    @Override
    public Map<String, Object> getUserAndDictDetail(Integer userId) {
        Map<String, Object> map = new HashMap<>(2);
        UserInfo userInfo = baseMapper.selectById(userId);
        userInfo.getParam().put("authStater", AuthStatusEnum.getStatusNameByStatus(userInfo.getAuthStatus()));
        userInfo.getParam().put("status", userInfo.getStatus() == 0 ? "锁定" : "正常");
        //获取就诊人信息
        List<Patient> userPatient = patientService.findUserPatient(userId);
        map.put("userInfo", userInfo);
        map.put("userPatient", userPatient);
        return map;
    }

    @Override
    public boolean approvalAuthStatus(Integer userId, Integer authStatue) {
        //2标识提供 -1标识不通过
        if (authStatue == 2 || authStatue == -1) {
            UserInfo userInfo = baseMapper.selectById(userId);
            userInfo.setAuthStatus(authStatue);
            int result = baseMapper.updateById(userInfo);
            return result > 0;
        }
        return false;
    }
}
